package com.huawei.zyb.taskManager.domain.requirement.entity;

import com.huawei.zyb.taskManager.domain.requirement.valueobject.*;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 需求聚合根
 * 管理功能需求和关联任务
 */
public class Requirement {
    private RequirementId id;
    private RequirementTitle title;
    private RequirementDescription description;
    private RequirementStatus status;
    private RequirementPriority priority;
    private Long projectId; // 所属项目ID
    private String ownerId; // 需求负责人ID
    private LocalDateTime expectedCompletionDate; // 预期完成时间
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    // 私有构造函数，强制使用工厂方法
    private Requirement() {}

    /**
     * 创建新需求（数据库自动生成ID）
     */
    public static Requirement create(
            RequirementTitle title,
            RequirementDescription description,
            RequirementPriority priority,
            Long projectId,
            String ownerId) {
        return create(title, description, priority, projectId, ownerId, null);
    }
    
    /**
     * 创建新需求（数据库自动生成ID，包含预期完成时间）
     */
    public static Requirement create(
            RequirementTitle title,
            RequirementDescription description,
            RequirementPriority priority,
            Long projectId,
            String ownerId,
            LocalDateTime expectedCompletionDate) {
        
        Objects.requireNonNull(projectId, "需求必须关联到有效的项目");
        // ownerId可以为null，表示暂未分配负责人
        
        Requirement requirement = new Requirement();
        requirement.id = null; // 让数据库自动生成ID
        requirement.title = title;
        requirement.description = description;
        requirement.status = RequirementStatus.DRAFT;
        requirement.priority = priority;
        requirement.projectId = projectId;
        requirement.ownerId = ownerId;
        requirement.expectedCompletionDate = expectedCompletionDate;
        requirement.createdAt = LocalDateTime.now();
        requirement.updatedAt = LocalDateTime.now();
        
        return requirement;
    }

    /**
     * 创建需求（指定ID）
     */
    public static Requirement create(
            RequirementId id,
            RequirementTitle title,
            RequirementDescription description,
            RequirementPriority priority,
            Long projectId,
            String ownerId) {
        
        Objects.requireNonNull(projectId, "需求必须关联到有效的项目");
        // ownerId可以为null，表示暂未分配负责人
        
        Requirement requirement = new Requirement();
        requirement.id = id;
        requirement.title = title;
        requirement.description = description;
        requirement.status = RequirementStatus.DRAFT;
        requirement.priority = priority;
        requirement.projectId = projectId;
        requirement.ownerId = ownerId;
        requirement.createdAt = LocalDateTime.now();
        requirement.updatedAt = LocalDateTime.now();
        
        return requirement;
    }

    /**
     * 从数据库数据恢复需求对象
     */
    public static Requirement restore(
            RequirementId id,
            RequirementTitle title,
            RequirementDescription description,
            RequirementStatus status,
            RequirementPriority priority,
            Long projectId,
            String ownerId,
            LocalDateTime createdAt,
            LocalDateTime updatedAt) {
        
        Requirement requirement = new Requirement();
        requirement.id = id;
        requirement.title = title;
        requirement.description = description;
        requirement.status = status;
        requirement.priority = priority;
        requirement.projectId = projectId;
        requirement.ownerId = ownerId;
        requirement.createdAt = createdAt;
        requirement.updatedAt = updatedAt;
        
        return requirement;
    }
    
    /**
     * 从数据库数据恢复需求对象（包含预期完成时间）
     */
    public static Requirement restore(
            RequirementId id,
            RequirementTitle title,
            RequirementDescription description,
            RequirementStatus status,
            RequirementPriority priority,
            Long projectId,
            String ownerId,
            LocalDateTime expectedCompletionDate,
            LocalDateTime createdAt,
            LocalDateTime updatedAt) {
        
        Requirement requirement = new Requirement();
        requirement.id = id;
        requirement.title = title;
        requirement.description = description;
        requirement.status = status;
        requirement.priority = priority;
        requirement.projectId = projectId;
        requirement.ownerId = ownerId;
        requirement.expectedCompletionDate = expectedCompletionDate;
        requirement.createdAt = createdAt;
        requirement.updatedAt = updatedAt;
        
        return requirement;
    }

    /**
     * 更新需求状态
     */
    public void updateStatus(RequirementStatus newStatus) {
        if (!this.status.canTransitionTo(newStatus)) {
            throw new IllegalStateException(
                String.format("需求状态不能从[%s]转换到[%s]", 
                    this.status.getDescription(), newStatus.getDescription())
            );
        }
        
        this.status = newStatus;
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 更新需求信息
     */
    public void updateInfo(
            RequirementTitle title, 
            RequirementDescription description, 
            RequirementPriority priority) {
        
        if (this.status.isFinalState()) {
            throw new IllegalStateException("已完成或已取消的需求不能修改信息");
        }
        
        this.title = Objects.requireNonNull(title, "需求标题不能为空");
        this.description = Objects.requireNonNull(description, "需求描述不能为空");
        this.priority = Objects.requireNonNull(priority, "需求优先级不能为空");
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 分配需求负责人
     */
    public void assignOwner(String ownerId) {
        if (this.status.isFinalState()) {
            throw new IllegalStateException("已完成或已取消的需求不能重新分配负责人");
        }
        
        this.ownerId = Objects.requireNonNull(ownerId, "需求负责人不能为空");
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 激活需求（从草稿状态转为活跃状态）
     */
    public void activate() {
        if (this.ownerId == null) {
            throw new IllegalStateException("需求必须指定负责人才能激活");
        }
        updateStatus(RequirementStatus.ACTIVE);
    }

    /**
     * 完成需求
     */
    public void complete() {
        updateStatus(RequirementStatus.COMPLETED);
    }

    /**
     * 取消需求
     */
    public void cancel() {
        updateStatus(RequirementStatus.CANCELLED);
    }

    /**
     * 检查是否可以创建任务
     */
    public boolean canCreateTasks() {
        return this.status.canCreateTasks();
    }

    /**
     * 检查是否已完成
     */
    public boolean isCompleted() {
        return this.status == RequirementStatus.COMPLETED;
    }

    /**
     * 检查是否为终态
     */
    public boolean isFinalState() {
        return this.status.isFinalState();
    }

    /**
     * 检查是否为草稿状态
     */
    public boolean isDraft() {
        return this.status == RequirementStatus.DRAFT;
    }

    // Getters
    public RequirementId getId() { return id; }
    public RequirementTitle getTitle() { return title; }
    public RequirementDescription getDescription() { return description; }
    public RequirementStatus getStatus() { return status; }
    public RequirementPriority getPriority() { return priority; }
    public Long getProjectId() { return projectId; }
    public String getOwnerId() { return ownerId; }
    public LocalDateTime getExpectedCompletionDate() { return expectedCompletionDate; }
    public LocalDateTime getCreatedAt() { return createdAt; }
    public LocalDateTime getUpdatedAt() { return updatedAt; }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Requirement that = (Requirement) obj;
        return Objects.equals(id, that.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    @Override
    public String toString() {
        return "Requirement{" +
                "id=" + id +
                ", title=" + title +
                ", status=" + status +
                ", priority=" + priority +
                "}";
    }
}